package com.uyayo.system.authority.service.impl;

import com.uyayo.framework.common.exception.CodeMultipleException;
import com.uyayo.framework.common.exception.ParentNotFoundException;
import com.uyayo.framework.common.util.CodeUtil;
import com.uyayo.system.authority.entity.SysOrganization;
import com.uyayo.system.authority.entity.SysOrganizationResource;
import com.uyayo.system.authority.entity.SysResource;
import com.uyayo.system.authority.entity.SysRoleResource;
import com.uyayo.system.authority.mapper.SysOrganizationResourceMapper;
import com.uyayo.system.authority.mapper.SysResourceMapper;
import com.uyayo.system.authority.mapper.SysRoleResourceMapper;
import com.uyayo.system.authority.model.SysResourceCondition;
import com.uyayo.system.authority.service.SysResourceService;
import com.uyayo.system.authority.service.SysRoleService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.List;


@Service("sysResourceService")
public class SysResourceServiceImpl implements SysResourceService {
	
	private final SysResourceMapper resourceMapper;

	private final SysRoleResourceMapper sysRoleResourceMapper;

	private final SysOrganizationResourceMapper sysOrganizationResourceMapper;

	private final SysRoleService roleService;

	@Autowired
	public SysResourceServiceImpl(SysResourceMapper resourceMapper, SysRoleResourceMapper sysRoleResourceMapper, SysOrganizationResourceMapper sysOrganizationResourceMapper, SysRoleService roleService) {
		this.resourceMapper = resourceMapper;
		this.sysRoleResourceMapper = sysRoleResourceMapper;
		this.sysOrganizationResourceMapper = sysOrganizationResourceMapper;
		this.roleService = roleService;
	}

	@Override
	public List<SysResource> selectSysResourceByUserId(SysResourceCondition sysResourceCondition){
		return resourceMapper.selectSysResourceByUserId(sysResourceCondition);
	}

	@Override
	public List<SysResource> selectSysResource(SysResourceCondition sysResourceCondition){
		return resourceMapper.selectSysResource(sysResourceCondition);
	}

	@Override
	public List<SysResource> resourceTreeGrid(SysResource resource) {
		List<SysResource> resources;
		Example example = new Example(SysResource.class);
		Example.Criteria criteria = example.createCriteria();
		criteria.andEqualTo(resource);
		example.setOrderByClause("t_sys_resource.sort_order ASC");
		resources = resourceMapper.selectByExample(example);
		return resources;
	}


	@Override
	public List<SysResource> selectResourceAll(SysResource resource) {
		List<SysResource> resources = new ArrayList<>();
		try {
			Example example = new Example(SysOrganization.class);
			resources = resourceMapper.selectByExample(example);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return resources;
	}

	@Override
	public SysResource selectResourceById(String id) {
		SysResource resource = new SysResource();
		try {
			resource = resourceMapper.selectByPrimaryKey(id);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return resource;
	}

	@Override
	public int selectCountByParentId(String parentId) {
		SysResource resource = new SysResource();
		resource.setParentId(parentId);
		return resourceMapper.selectCount(resource);
	}

	@Override
	public int saveResource(SysResource resource) throws CodeMultipleException, ParentNotFoundException {
		String parentId = resource.getParentId();
		SysResource sysResourceCondition = new SysResource();
		sysResourceCondition.setCode(resource.getCode());
		SysResource sysResourceTest = resourceMapper.selectOne(sysResourceCondition);
		if(sysResourceTest!=null){
			throw new CodeMultipleException("Code multiple error!");
		}
		if(StringUtils.isNotEmpty(parentId)){
			SysResource sysResourceParent = selectResourceById(parentId);
			if(sysResourceParent==null){
				throw new ParentNotFoundException("Parent not found!");
			}
		}

		int count = resourceMapper.insertSelective(resource);
		if(count >0){
			updateHasChildrennToParent( parentId);
			SysRoleResource sysRoleResource = new SysRoleResource();
			sysRoleResource.setId(CodeUtil.getTimeSequenceAsRandomCode());
			sysRoleResource.setResourceId(resource.getId());
			sysRoleResource.setRoleId("0");
			this.sysRoleResourceMapper.insertSelective(sysRoleResource);//权限添加到超级管理员
		}
		return count;
	}

	/**
	 * 迭代检查选择的上级id是否是自己的子级
	 * @param parentIdOld 原上级id
	 * @param parentIdNew	新上级id
	 * @param sysResourceChild 子资源
	 * @param sysResourceParent 父资源
	 */
	private void recursiveCheckParentIsChildren(String parentIdOld, String parentIdNew, SysResource sysResourceChild, SysResource sysResourceParent){
		if (selectCountByParentId(sysResourceChild.getId()) > 0) {
			Example example = new Example(SysResource.class);
			Example.Criteria criteria = example.createCriteria();
			criteria.andEqualTo("parentId",sysResourceChild.getId());
			List<SysResource> sysResources = resourceMapper.selectByExample(example);
			if (!sysResources.isEmpty()) {
				for(SysResource sysResource:sysResources){
					if(StringUtils.equals(sysResource.getId(),parentIdNew)){
						sysResourceParent.setParentId(parentIdOld);
						resourceMapper.updateByPrimaryKeySelective(sysResourceParent);
					}else {
						recursiveCheckParentIsChildren(parentIdOld, parentIdNew, sysResource, sysResourceParent);
					}
				}
			}
		}
	}
	@Override
	public int updateResource(SysResource resource) throws ParentNotFoundException, CodeMultipleException {

		SysResource sysResourceCondition = new SysResource();
		sysResourceCondition.setCode(resource.getCode());
		SysResource sysResourceTest = resourceMapper.selectOne(sysResourceCondition);
		if(sysResourceTest!=null && !StringUtils.equals(resource.getId(),sysResourceTest.getId())){
			throw new CodeMultipleException("Code multiple error!");
		}

		SysResource sysResourceOld = selectResourceById(resource.getId());

		String parentId = resource.getParentId();
		if(StringUtils.isNotEmpty(parentId)){

			//获取修改的父级资源
			SysResource sysResourceParent = selectResourceById(parentId);
			if(sysResourceParent==null){
				throw new ParentNotFoundException("Parent not found!");
			}
			if (selectCountByParentId(sysResourceOld.getId()) > 0) {
				Example example = new Example(SysResource.class);
				Example.Criteria criteria = example.createCriteria();
				criteria.andEqualTo("parentId",sysResourceOld.getId());
				List<SysResource> sysResources = resourceMapper.selectByExample(example);
				if (!sysResources.isEmpty()) {
					for(SysResource sysResource:sysResources){
						if(StringUtils.equals(sysResource.getId(),parentId)){
							sysResourceParent.setParentId(sysResourceOld.getParentId());
							resourceMapper.updateByPrimaryKeySelective(sysResourceParent);
						}else{
							recursiveCheckParentIsChildren(sysResourceOld.getParentId(),resource.getParentId(),sysResource,sysResourceParent);
						}
					}
				}
			}
		}
		if(selectCountByParentId(resource.getId())>0) {
			resource.setHasChildren(true);
		}else{
			resource.setHasChildren(false);
		}
		int count = resourceMapper.updateByPrimaryKeySelective(resource);
		if(count<=0){
			return count;
		}
		updateHasChildrennToParent(parentId);
		if(sysResourceOld!=null){
			updateHasChildrennToParent(sysResourceOld.getParentId());
		}
		return count;
	}

	/**
	 * 修改父资源是否含子资源
	 * @param parentId 父资源id
	 */
	private void  updateHasChildrennToParent(String parentId){
		if(StringUtils.isNotEmpty(parentId)){
			SysResource sysResource = new SysResource();
			sysResource.setId(parentId);
			if(selectCountByParentId(parentId)>0) {
				sysResource.setHasChildren(true);
			}else{
				sysResource.setHasChildren(false);
			}
			resourceMapper.updateByPrimaryKeySelective(sysResource);
		}
	}

	@Override
	public int deleteResource(String id) {

		if (selectCountByParentId(id) > 0) {
			Example example = new Example(SysResource.class);
			Example.Criteria criteria = example.createCriteria();
			criteria.andEqualTo("parentId",id);
			List<SysResource> sysResources = resourceMapper.selectByExample(example);
			if (!sysResources.isEmpty()) {
				for(SysResource sysResource:sysResources){
					recursiveDelete( sysResource);
				}
			}
		}
		return delete(id);
	}

	/**
	 * 递归删除资源
	 * @param sysResource 资源
	 */
	private void recursiveDelete(SysResource sysResource){

		if (selectCountByParentId(sysResource.getId()) > 0) {
			Example example = new Example(SysResource.class);
			Example.Criteria criteria = example.createCriteria();
			criteria.andEqualTo("parentId",sysResource.getId());
			List<SysResource> sysResources = resourceMapper.selectByExample(example);
			if (!sysResources.isEmpty()) {
				for(SysResource sysResourceChild:sysResources){
					recursiveDelete(sysResourceChild);
				}
			}
		}
		delete(sysResource.getId());
	}

	public int delete(String id) {
		SysResource sysResource = resourceMapper.selectByPrimaryKey(id);
		int count = resourceMapper.deleteByPrimaryKey(id);
		if(count<=0){
			return count;
		}
		updateHasChildrennToParent(sysResource!=null?sysResource.getParentId():null);

		Example exampleO = new Example(SysOrganizationResource.class);
		Example.Criteria criteriaO = exampleO.createCriteria();
		criteriaO.andEqualTo("resourceId", id);
		sysOrganizationResourceMapper.deleteByExample(exampleO);

		Example exampleR = new Example(SysRoleResource.class);
		Example.Criteria criteriaR = exampleR.createCriteria();
		criteriaR.andEqualTo("resourceId", id);
		sysRoleResourceMapper.deleteByExample(exampleR);
		return count;
	}

	
}
